package com.zjuee.web.basic.file.service.impl;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.OSSObject;
import com.zjuee.base.bean.response.CommonResultCode;
import com.zjuee.base.exception.BaseException;
import com.zjuee.base.utils.Base64Utils;
import com.zjuee.base.utils.FileUtil;
import com.zjuee.service.basic.file.service.FileService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import com.zjuee.web.basic.file.util.StringsUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Calendar;

/**
 * @author wuliang
 * @since 1.0
 */
@Service
public class FileServiceImpl implements FileService {

    @Value("${file.management.oss.url}")
    private String ossUrl;

    @Value("${file.management.oss.accessKeyId}")
    private String ossAccessKeyId;

    @Value("${file.management.oss.accessKeySecret}")
    private String ossAccessKeySecret;

    @Value("${file.management.oss.bucketName}")
    private String ossBucketName;

    @Value("${file.management.oss.directoryName}")
    private String ossDirectoryName;

    private String uploadOSS(MultipartFile uploadFile, String modelName, String limitType) {
        InputStream inputStream = null;
        InputStream inputStreamValidate = null;

        try {
            inputStreamValidate = uploadFile.getInputStream();
            String fileName = uploadFile.getOriginalFilename();
            //文件名是否为空
            if(StringUtils.isBlank(fileName)){
                throw new BaseException(CommonResultCode.CONSUMER_ERR, "文件名字为空！");
            }
            fileName = StringsUtil.replaceAllStr(fileName);

            String[] names = fileName.split("\\.");
            //获取后缀
            String suffix = names[names.length-1];

            boolean fileTypeIsVaild =false;
            if(StringUtils.isNotBlank(limitType)){
                fileTypeIsVaild = FileUtil.checkSuffix(limitType, suffix);
            }else {
                fileTypeIsVaild = FileUtil.checkSuffix(suffix);
            }

            if(StringUtils.isNotBlank(limitType)){
                fileTypeIsVaild = true;
            }else {
                fileTypeIsVaild = FileUtil.CheckFileType(inputStreamValidate);
            }
            if (!fileTypeIsVaild) {
                throw new BaseException(CommonResultCode.CONSUMER_ERR, "文件格式错误！");
            }

            //获取年份，月份，天
            Calendar date = Calendar.getInstance();
            String year = String.valueOf(date.get(Calendar.YEAR));
            String month = String.valueOf(date.get(Calendar.MONTH)+1);
            String day = String.valueOf(date.get(Calendar.DAY_OF_MONTH));

            OSS ossClient = (new OSSClientBuilder()).build(ossUrl, ossAccessKeyId, ossAccessKeySecret);
//            String time = DateUtils.parse(new Date(), "yyyyMMddHHmmss");
            //拼接上传路径
            String pathName = ossDirectoryName + "/" + modelName + "/" + year+"/"+month+"/"+day+"/"+System.currentTimeMillis() + "_" + fileName;
            inputStream = uploadFile.getInputStream();
            ossClient.putObject(ossBucketName, pathName, inputStream);
            ossClient.shutdown();
            return pathName;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(CommonResultCode.CONSUMER_ERR, e.getMessage());
        } finally {
            close(inputStream, inputStreamValidate);
        }
    }


    @Override
    public String upload(MultipartFile uploadFile, String modelName) {
        return uploadOSS(uploadFile, modelName, "");
    }

    @Override
    public String upload(MultipartFile uploadFile, String limitType,
                         String modelName) {
        return uploadOSS(uploadFile, modelName, limitType);
    }

  @Override
    public void download(String url) {
      HttpServletRequest request =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
      HttpServletResponse response = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        OutputStream outputStream = null;

        if (!StringUtils.isEmpty(url)) {
          if (url.startsWith("/")) {
            url = "shwmmold" + url;
          }
        }

        try {
            OSS ossClient = (new OSSClientBuilder()).build(ossUrl, ossAccessKeyId, ossAccessKeySecret);
            OSSObject ossObject = ossClient.getObject(ossBucketName, url);
            String fileName = StringsUtil.subUrl(url);
            String agent = request.getHeader("USER-AGENT");

            if (agent != null && agent.toLowerCase().indexOf("firebox") > 0) {
              fileName = "=?UTF-8?B?" + (new String(Base64Utils.encode(fileName.getBytes("UTF-8"))));
            } else {
              fileName = URLEncoder.encode(fileName, "UTF-8");
            }

            response.setContentLength(Integer.valueOf(ossObject.getObjectMetadata().getContentLength() + ""));
            response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
            bis = new BufferedInputStream(ossObject.getObjectContent());
            outputStream = response.getOutputStream();
            bos = new BufferedOutputStream(outputStream);
            byte[] buffer = new byte[1024];
            int length;

            while ((length = bis.read(buffer)) > 0) {
              bos.write(buffer, 0, length);
            }

            outputStream.flush();
            bos.flush();
            ossClient.shutdown();

        } catch (Exception e) {
          e.printStackTrace();
        } finally {
          close(bos, bis, outputStream);
        }
    }

    @Override
    public void showImage(String path) {
        HttpServletResponse response = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
      if (StringUtils.isNotEmpty(path) && !"null".equals(path)) {
        BufferedOutputStream bos = null;
        BufferedInputStream bis = null;
        OSS ossClient = null;
        OutputStream outputStream = null;
        response.setContentType("image/jpg");

        try {
          outputStream = response.getOutputStream();
          ossClient = (new OSSClientBuilder()).build(ossUrl, ossAccessKeyId, ossAccessKeySecret);
          OSSObject ossObject = ossClient.getObject(ossBucketName, path);
          bis = new BufferedInputStream(ossObject.getObjectContent());
          bos = new BufferedOutputStream(outputStream);
          byte[] buffer = new byte[1024];
          int length;

          while ((length = bis.read(buffer)) > 0) {
            bos.write(buffer, 0, length);
          }

          outputStream.flush();
          bos.flush();
          ossClient.shutdown();
        } catch (IOException e) {
          e.printStackTrace();
        } finally {
          close(bos, bis, outputStream);
        }
      }

    }

    private void close(Closeable... closeableList) {
      for (Closeable closeable : closeableList) {
        try {
          if (closeable != null) {
            closeable.close();
          }
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }

//    private boolean notTextFileTypeCheck(InputStream inputStream) throws IOException {
//      boolean isVaild = false;
//      byte[] buffer = new byte[10];
//      inputStream.read(buffer);
//
//
//      //获取当前文件的真实类型
//      String fileType = getTrueFileType(bytesToHexFileTypeString(buffer));
//
//      //指定文件类型中是否匹配当前文件类型
//      if (fileType != null) {
//        isVaild = true;
//      }
//      return isVaild;
//    }
//
//    private String getTrueFileType(String s) {
//      for (FileTypeEnum fileTypeEnum : FileTypeEnum.values()) {
//        if (s.startsWith(fileTypeEnum.getValue())) {
//          return fileTypeEnum.toString();
//        }
//      }
//      return null;
//    }
//
//    private String bytesToHexFileTypeString(byte[] buffer) {
//      StringBuilder hexFileTypeStr = new StringBuilder();
//      for (byte b : buffer) {
//        String hexString = Integer.toHexString(b & 0xFF);
//        if (hexString.length() < 2) {
//          hexFileTypeStr.append("0");
//        }
//        hexFileTypeStr.append(hexString);
//      }
//      return hexFileTypeStr.toString();
//    }

}
